home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxcode / fmplay11 / fmplay.c < prev    next >
C/C++ Source or Header  |  1993-07-26  |  5KB  |  202 lines

  1. #include<stdlib.h>
  2. #include<stdio.h>
  3. #include<dos.h>
  4. #include"adlib.h"
  5. #include"fmplay.h"
  6.  
  7. /**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***\
  8.  * This module MUST be compiled with stack checking OFF in BC 3.0 *
  9. \**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING***/
  10.  
  11. /* We wish that THIS would turn stack checking off, but it doesn't work */
  12. #pragma -N-
  13.    
  14. #ifdef __cplusplus
  15. #define __CPPARGS ...
  16. #else
  17. #define __CPPARGS
  18. #endif
  19.  
  20. #define NMVOICES 11
  21.  
  22. /* freqTable[60] is the frequency for middle C. 61=c# 62=d &c */
  23. int freqTable[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,516,547,580,614,651,
  24. 689,730,774,820,869,920,975,1540,1571,1604,1638,1675,1713,1754,1798,1844,1893,
  25. 1944,1999,2564,2595,2628,2662,2699,2737,2778,2822,2868,2917,2968,3023,3588,
  26. 3619,3652,3686,3723,3761,3802,3846,3892,3941,3992,4047,4612,4643,4676,4710,
  27. 4747,4785,4826,4870,4916,4965,5016,5071,5636,5667,5700,5734,5771,5809,5850,
  28. 5894,5940,5989,6040,6095,6660,6691,6724,6758,6795,6833,6874,6918,6964,7013,
  29. 7064,7119,7684,7715,7748,7782,7819};
  30.  
  31. /* The frequency table was generated by the following code: */
  32. #if 0
  33. void initFreqTable(void)
  34. {double f,fn;
  35.  BYTE b;
  36.  int i;
  37.  f=16.352;
  38.  for (i=12;i<108;i++)
  39.     {b=7-((int)(log(6208.43115/f)/0.69314718));
  40.       fn=f*(1 << (7-b))/6.0688476;
  41.      freqTable[i]=(b << 10)+(int)fn;
  42.      f*=1.059463094;
  43.     }
  44. }
  45. #endif
  46.  
  47. void interrupt (*oldHandler)(__CPPARGS)=NULL;
  48. volatile static BYTE *currentSong=NULL,*cp;
  49. volatile static int noteTimer[NMVOICES]={0,0,0,0,0,0,0,0,0,0,0},
  50.    pauseTime,tempoDivider,tdc;
  51. volatile int songPlaying=0,interruptCount=0;
  52. int timerDivisor,loop;
  53.  
  54. int FMSongPlaying(void)
  55. {return songPlaying;
  56. }
  57.  
  58. void FMPlayNextTick(void)
  59. {int i,j,k,nonePlaying;
  60.  if (!songPlaying || --tdc>0) return;
  61.  tdc=tempoDivider;
  62.  nonePlaying=1;
  63.  for (i=0;i<NMVOICES;i++)
  64.     {if (noteTimer[i]>0)
  65.     {nonePlaying=0;
  66.      if (--noteTimer[i]<=0)
  67.         FMKeyOff(i);
  68.     }
  69.     }
  70.  if (!currentSong) /* current song goes NULL when the script has run out */
  71.     {if (nonePlaying) /* songPlaying goes null when all the notes turn off */
  72.     {songPlaying=0;
  73.     }
  74.      return;
  75.     }
  76.  if (--pauseTime<=0)
  77.     {pauseTime=0;
  78.      while (!pauseTime)
  79.     {switch (*cp)
  80.         {case 0: /* play note */
  81.         i=cp[1];
  82.         j=cp[2];
  83.         k=*((int *)(cp+3));
  84.         FMKeyOn(i,freqTable[j]);
  85.         noteTimer[i]=k;
  86.         cp+=5;
  87.         break;
  88.           case 2: /* change instrument */
  89.         i=cp[1];
  90.         j=cp[2];
  91.         FMSetVoice(i,(FMInstrument *)(currentSong+2+sizeof(FMInstrument)*j));
  92.         cp+=3;
  93.         break;
  94.           case 3: /* pause */
  95.         i=*((int *)(cp+1));
  96.         pauseTime=i;
  97.         cp+=3;
  98.         break;
  99.           case 4: /* end of song */
  100.         if (!loop)
  101.            currentSong=NULL;
  102.         else
  103.            {pauseTime=loop;
  104.             cp=currentSong+(*(currentSong+1))*sizeof(FMInstrument)+2;
  105.            }
  106.         return;
  107.            }
  108.     }
  109.     }
  110. }
  111.  
  112. void FMStartSong(BYTE *songData,int speed,int loop1)
  113. {int i;
  114.  disable(); /* disable interupts */
  115.  tempoDivider=speed;
  116.  tdc=0;
  117.  currentSong=songData;
  118.  songPlaying=1;
  119.  pauseTime=0;
  120.  cp=currentSong+(*(currentSong+1))*sizeof(FMInstrument)+2;
  121.  FMReset(*currentSong);
  122.  for (i=0;i<NMVOICES;i++)
  123.     noteTimer[i]=0;
  124.  loop=loop1;
  125.  enable(); /* enable interupts */
  126. }
  127.  
  128. void FMStopSong(void)
  129. {disable(); /* disable interupts */
  130.  currentSong=NULL;
  131.  while (songPlaying)
  132.     FMPlayNextTick();
  133.  enable(); /* enable interupts */
  134. }
  135.  
  136.  
  137. BYTE *FMLoadSong(char *name)
  138. {FILE *ifile;
  139.  BYTE *rol;
  140.  int rolSize;
  141.  ifile=fopen(name,"rb");
  142.  if (!ifile)
  143.     return NULL;
  144.  fseek(ifile,0,SEEK_END);
  145.  rolSize=ftell(ifile);
  146.  fseek(ifile,0,SEEK_SET);
  147.  rol=(BYTE *)malloc(sizeof(BYTE)*rolSize);
  148.  if (!rol)
  149.     {fclose(ifile);
  150.      return NULL;
  151.     }
  152.  if (fread(rol,sizeof(BYTE),rolSize,ifile)!=rolSize)
  153.     {fclose(ifile);
  154.      return NULL;
  155.     }
  156.  fclose(ifile);
  157.  return rol;
  158. }
  159.  
  160.  
  161. void interrupt FMISR(__CPPARGS)
  162. {FMPlayNextTick();
  163.  if (++interruptCount>=timerDivisor)
  164.     {interruptCount=0;
  165.      oldHandler();
  166.     }
  167. }
  168.  
  169. void FMInstallISR(int td)
  170. {unsigned int timerSpeed;
  171.  timerDivisor=td;
  172.  if (td!=1)
  173.     {/* tell the timer to speed up the ticks */
  174.      timerSpeed=0x10000L/td;
  175.      disable();
  176.      outp(0x43, 0x36);
  177.      outp(0x40, timerSpeed & 0xff);
  178.      outp(0x40, timerSpeed >> 8);
  179.      enable();
  180.     }
  181.  oldHandler = _dos_getvect(0x1c);
  182.  _dos_setvect(0x1c, FMISR);
  183. }
  184.  
  185. void FMRemoveISR(void)
  186. {if (oldHandler)
  187.     {_dos_setvect(0x1c, oldHandler);
  188.      if (timerDivisor!=1)
  189.     {/* return the ticks to normal speed */
  190.      disable();
  191.      outp(0x43, 0x36);
  192.      outp(0x40, 0);
  193.      outp(0x40, 0);
  194.      enable();
  195.     }
  196.     }
  197. }
  198.  
  199.  
  200.  
  201.  
  202.